package model

import (
	"context"
	"gorm.io/gorm"
)

type (
	Groups interface {
		Insert(ctx context.Context, group, name string, apis string) error
		FindOne(ctx context.Context, id int64) (*AuthxGroups, error)
		FindByGroupName(ctx context.Context, groupName string) (*AuthxGroups, error)
		FindByGroups(ctx context.Context, groups []string) ([]*AuthxGroups, error)
		FindAll(ctx context.Context) ([]*AuthxGroups, error)
		Delete(ctx context.Context, id int64) error
		Update(ctx context.Context, id int64, group, name string, apis string) error
	}

	defaultGroups struct {
		db *gorm.DB
	}
)

func NewGroups(db *gorm.DB) Groups {
	return &defaultGroups{
		db: db,
	}
}

func (d *defaultGroups) model() *gorm.DB {
	return d.db.Model(&AuthxGroups{})
}

func (d *defaultGroups) Insert(ctx context.Context, group, name string, apis string) error {
	return d.db.Create(&AuthxGroups{
		Group: group,
		Apis:  apis,
		Name:  name,
	}).Error
}

func (d *defaultGroups) FindOne(ctx context.Context, id int64) (*AuthxGroups, error) {
	var result AuthxGroups
	err := d.model().Where("id = ?", id).First(&result).Error

	switch err {
	case nil:
		return &result, nil
	case gorm.ErrRecordNotFound:
		return nil, ErrNotFound
	default:
		return nil, err
	}
}

func (d *defaultGroups) FindByGroupName(ctx context.Context, groupName string) (*AuthxGroups, error) {
	var result AuthxGroups
	err := d.model().Where("`group` = ?", groupName).First(&result).Error

	switch err {
	case nil:
		return &result, nil
	case gorm.ErrRecordNotFound:
		return nil, ErrNotFound
	default:
		return nil, err
	}
}

func (d *defaultGroups) FindByGroups(ctx context.Context, groups []string) ([]*AuthxGroups, error) {
	var result []*AuthxGroups
	err := d.model().Where("`group` in (?)", groups).Find(&result).Error
	switch err {
	case nil:
		return result, nil
	default:
		return nil, err
	}
}

func (d *defaultGroups) FindAll(ctx context.Context) ([]*AuthxGroups, error) {
	var list []*AuthxGroups
	if err := d.model().Find(&list).Error; err != nil {
		return nil, err
	}
	return list, nil
}

func (d *defaultGroups) Delete(ctx context.Context, id int64) error {
	return d.model().Where("id = ?", id).Delete(&AuthxGroups{}).Error
}

func (d *defaultGroups) Update(ctx context.Context, id int64, group, name string, apis string) error {
	result := d.model().Where("id = ?", id).Updates(&AuthxGroups{
		Group: group,
		Apis:  apis,
		Name:  name,
	})

	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return ErrNotFound
	}
	return nil
}
